/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.mocking;

import org.jmock.core.Stub;
import org.jmock.core.stub.ReturnStub;
import org.jmock.core.stub.StubSequence;
import org.jmock.core.stub.ThrowStub;

import picounit.PicoUnitException;
import picounit.mocker.OccurencesMatcher;

import java.lang.reflect.Array;

class BaseConsequenceMatcher {
	private final ActiveRecordingPlaybackMock activeRecordingPlaybackMock;
	private final OccurencesMatcher occurencesMatcher;
	private final MockInvocationInspector mockInvocationInspector;

	public BaseConsequenceMatcher(ActiveRecordingPlaybackMock activeRecordingPlaybackMock,
		OccurencesMatcher occurencesMatcher, MockInvocationInspector mockInvocationInspector) {

		this.activeRecordingPlaybackMock = activeRecordingPlaybackMock;
		this.occurencesMatcher = occurencesMatcher;
		this.mockInvocationInspector = mockInvocationInspector;
	}

	public final OccurencesMatcher andRaise(Throwable toThrow) {
		return will(new ThrowStub(toThrow));
	}

	protected final ReturnStub returnValue(Object result) {
		return new ReturnStub(result);
	}

	protected final StubSequence returnConsecutiveValues(Object results) {
		Stub[] returnStubs = new Stub[Array.getLength(results)];
	
		for (int index = 0; index < returnStubs.length; index++ ) {
			returnStubs[index] = returnValue(Array.get(results, index));
		}
	
		return new StubSequence(returnStubs);
	}

	protected final boolean isArrayOfResults(Object result) {
		return result != null &&
			result.getClass().isArray() &&
			result.getClass().getComponentType().equals(
				getLastInvocationReturnType());
	}

	protected final OccurencesMatcher will(Stub stub) {
		activeRecordingPlaybackMock.setStub(stub);
	
		return occurencesMatcher;
	}

	@SuppressWarnings("unchecked")
	protected final <T> T createType(Class<T> type) {
		Class lastInvocationReturnType = getLastInvocationReturnType();

		try {
			return type.cast(lastInvocationReturnType.newInstance());
		}
		catch (InstantiationException e) {
			throw new PicoUnitException("Could not create type: " + lastInvocationReturnType.getName(), e);
		}
		catch (IllegalAccessException e) {
			throw new PicoUnitException("Could not create type: " + lastInvocationReturnType.getName(), e);
		}
	}

	protected final Class getLastInvocationReturnType() {
		return mockInvocationInspector.getLastInvocationReturnType();
	}
}
